/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bean;

import entity.Accion;
import entity.Inversor;
import facade.AccionFacadeLocal;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
import javax.persistence.NoResultException;

/**
 *
 * @author ari
 */
@Stateless
public class BeanAccion implements BeanAccionRemote {
    @EJB
    private BeanEmpresaRemote beanEmpresa;
    @EJB
    private BeanEstadisticaRemote beanEstadistica;
    
    @EJB
    private AccionFacadeLocal accionFacade;
    @PersistenceContext(unitName = "BolsaValor-ejbPU")
    private EntityManager em;

    public void persist(Object object) {
        em.persist(object);
    }

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")

    @Override
    public List<String> obtenerCompraInv(String login) {
        return em.createQuery("SELECT a.name FROM Accion a JOIN a.inversor i WHERE i.login = :login AND a.tipo = FALSE ORDER BY a.id", String.class)
                .setParameter("login", login)
                .getResultList();
    }

    @Override
    public List<String> obtenerVentaInv(String login) {
        return em.createQuery("SELECT a.name FROM Accion a JOIN a.inversor i WHERE i.login = :login AND a.tipo = TRUE ORDER BY a.id", String.class)
                .setParameter("login", login)
                .getResultList();
    }

    @Override
    public boolean deleteVenta(String login, String empresa, double monto) {
        Accion a;
        try {
            a = em.createQuery("SELECT a FROM Accion a JOIN a.inversor i WHERE a.name = :empresa AND i.login = :login AND a.monto = :monto AND a.tipo = TRUE", Accion.class)
                    .setParameter("login", login)
                    .setParameter("empresa", empresa)
                    .setParameter("monto", monto)
                    .getSingleResult();
        } catch (NoResultException e) {
            return false;
        }
            
        accionFacade.remove(a);
        return true;
    }

    @Override
    public boolean deleteCompra(String login, String empresa, double monto) {
        Accion a;
        try {
            a = em.createQuery("SELECT a FROM Accion a JOIN a.inversor i WHERE a.name = :empresa AND i.login = :login AND a.monto = :monto AND a.tipo = FALSE", Accion.class)
                    .setParameter("login", login)
                    .setParameter("empresa", empresa)
                    .setParameter("monto", monto)
                    .getSingleResult();
        } catch (NoResultException e) {
            return false;
        }
            
        accionFacade.remove(a);
        return true;
    }

    @Override
    public boolean createCompra(String login, String empresa, int num, double monto) {
        int num1 = num;
        
        Inversor i = em.createQuery("SELECT i FROM Inversor i WHERE i.login = :login", Inversor.class)
                .setParameter("login", login)
                .getSingleResult();
                
        List<Accion> a = em.createQuery("SELECT a FROM Accion a JOIN a.inversor i WHERE a.name = :empresa AND i.login = :login AND a.monto = :monto AND a.tipo = FALSE", Accion.class)
                .setParameter("login", login)
                .setParameter("empresa", empresa)
                .setParameter("monto", monto)
                .getResultList();
        List<Accion> b = em.createQuery("SELECT a FROM Accion a WHERE a.name = :empresa AND a.monto <= :monto AND a.tipo = TRUE ORDER BY a.monto", Accion.class)
                .setParameter("empresa", empresa)
                .setParameter("monto", monto)
                .getResultList();
        
        Accion accion = new Accion();
        if(b.isEmpty()) {
            if(!beanEstadistica.addEstadistica(0, 0, 0.0, num1, monto, empresa))
                return false;
            if(!beanEmpresa.addEmpresa(empresa, monto, 0.0)) 
                return false;
            
            if(a.isEmpty()) {
                accion.setInversor(i);
                accion.setName(empresa);
                accion.setMonto(monto);
                accion.setNum(num);
                accion.setTipo(AccionFacadeLocal.COMPRA);
                accionFacade.create(accion);        
            } else {
                accion = a.get(0);
                accion.setNum(accion.getNum()+num);
                accionFacade.edit(accion);
            }
            
            if(em.contains(accion))
                return true;
        } else {
            if(a.isEmpty()) {
                accion.setInversor(i);
                accion.setName(empresa);
                accion.setMonto(monto);
                accion.setTipo(AccionFacadeLocal.COMPRA);
            } else {
                accion = a.get(0);
                num += accion.getNum();
            }
            
            int aux = num;
            for(Accion temp : b) {
                if(num >= temp.getNum()) {
                    num -= temp.getNum();
                    accionFacade.remove(temp);
                    
                    if(num == 0) {
                        if(!beanEstadistica.addEstadistica(aux, 0, 0.0, num1, monto, empresa))
                            return false;
                        if(!beanEmpresa.addEmpresa(empresa, monto, 0.0)) 
                            return false;
                        return true;
                    }
                        
                } else {
                    temp.setNum(temp.getNum() - num);
                    accionFacade.edit(temp);

                    if(!beanEstadistica.addEstadistica(num, 0, 0.0, num1, monto, empresa))
                        return false;
                    if(!beanEmpresa.addEmpresa(empresa, monto, 0.0)) 
                        return false;
                    
                    return true;
                }
            }
            
            accion.setNum(num);
            
            if(!beanEstadistica.addEstadistica(aux-num, 0, 0.0, num1, monto, empresa))
                return false;
            if(!beanEmpresa.addEmpresa(empresa, monto, 0.0)) 
                return false;
            
            accionFacade.create(accion);
            
            if(em.contains(accion))
                return true;

            em.flush();
            // No se creo
            return false;
        }

        em.flush();

        // No se actualizo
        return false;
    }

    @Override
    public boolean createVenta(String login, String empresa, int num, double monto) {
        int num1 = num;
        Inversor i = em.createQuery("SELECT i FROM Inversor i WHERE i.login = :login", Inversor.class)
                .setParameter("login", login)
                .getSingleResult();
                
        List<Accion> a = em.createQuery("SELECT a FROM Accion a JOIN a.inversor i WHERE a.name = :empresa AND i.login = :login AND a.monto = :monto AND a.tipo = TRUE", Accion.class)
                .setParameter("login", login)
                .setParameter("empresa", empresa)
                .setParameter("monto", monto)
                .getResultList();
        List<Accion> b = em.createQuery("SELECT a FROM Accion a WHERE a.name = :empresa AND a.monto >= :monto AND a.tipo = FALSE ORDER BY a.monto DESC", Accion.class)
                .setParameter("empresa", empresa)
                .setParameter("monto", monto)
                .getResultList();
        
        Accion accion = new Accion();
        if(b.isEmpty()) {
            if(!beanEstadistica.addEstadistica(0, num1, monto, 0, 0.0, empresa))
                return false;
            if(!beanEmpresa.addEmpresa(empresa, 0.0, monto)) 
                return false;
            if(a.isEmpty()) {
                accion.setInversor(i);
                accion.setName(empresa);
                accion.setMonto(monto);
                accion.setNum(num);
                accion.setTipo(AccionFacadeLocal.VENTA);
                accionFacade.create(accion);        
            } else {
                accion = a.get(0);
                accion.setNum(accion.getNum()+num);
                accionFacade.edit(accion);
            }
            if(em.contains(accion))
                return true;
        } else {
            if(a.isEmpty()) {
                accion.setInversor(i);
                accion.setName(empresa);
                accion.setMonto(monto);
                accion.setTipo(AccionFacadeLocal.VENTA);
            } else {
                accion = a.get(0);
                num += accion.getNum();
            }
            
            int aux = num;
            for(Accion temp : b) {
                if(num >= temp.getNum()) {
                    num -= temp.getNum();
                    accionFacade.remove(temp);
                    
                    if(num == 0) {
                        if(!beanEstadistica.addEstadistica(aux, num1, monto, 0, 0.0, empresa))
                            return false;

                        if(!beanEmpresa.addEmpresa(empresa, 0.0, monto)) 
                            return false;

                        return true;
                    }
                } else {
                    temp.setNum(temp.getNum() - num);
                    accionFacade.edit(temp);

                    if(!beanEstadistica.addEstadistica(num, num1, monto, 0, 0.0, empresa))
                        return false;

                    if(!beanEmpresa.addEmpresa(empresa, 0.0, monto)) 
                        return false;

                    return true;
                }
            }
            
            accion.setNum(num);
            
            if(!beanEstadistica.addEstadistica(aux-num, num1, monto, 0, 0.0, empresa))
                return false;
            
            if(!beanEmpresa.addEmpresa(empresa, 0.0, monto)) 
                return false;
            
            accionFacade.create(accion);
            
            if(em.contains(accion))
                return true;

            em.flush();
            // No se creo
            return false;
        }

        em.flush();

        // No se actualizo
        return false;
    }

    @Override
    public Accion getOferta(String login, String empresa, double monto, boolean tipo) {
        Accion a;
        if(tipo = AccionFacadeLocal.COMPRA) {
            a = em.createQuery("SELECT a FROM Accion a JOIN a.inversor i WHERE a.name = :empresa AND i.login = :login AND a.monto = :monto AND a.tipo = FALSE", Accion.class)
                .setParameter("login", login)
                .setParameter("empresa", empresa)
                .setParameter("monto", monto)
                .getSingleResult();
        } else {
            a = em.createQuery("SELECT a FROM Accion a JOIN a.inversor i WHERE a.name = :empresa AND i.login = :login AND a.monto = :monto AND a.tipo = TRUE", Accion.class)
                .setParameter("login", login)
                .setParameter("empresa", empresa)
                .setParameter("monto", monto)
                .getSingleResult();
        }
        
        return a;
    }

    @Override
    public List<Long> getIdCompraInv(String login) {
        return em.createNamedQuery("Accion.findIdCompraByInversor", Long.class)
                .setParameter("login", login)
                .getResultList();
    }

    @Override
    public List<Long> getIdVentaInv(String login) {
        return em.createNamedQuery("Accion.findIdVentaByInversor", Long.class)
                .setParameter("login", login)
                .getResultList();
    }

    @Override
    public int getNum(Long id) {
        try {
            return em.createQuery("SELECT a FROM Accion a WHERE a.id = :id", Accion.class)
                .setParameter("id", id)
                .getSingleResult()
                .getNum();    
        } catch (Exception e) {
            return 0;
        }
    }

    @Override
    public double getMonto(Long id) {
        try {
            return em.createQuery("SELECT a FROM Accion a WHERE a.id = :id", Accion.class)
                    .setParameter("id", id)
                    .getSingleResult()
                    .getMonto();  
        } catch (Exception e) {
            return 0;
        }
    }

    @Override
    public boolean deleteOferta(Long id) {
        Accion a;
        try {
            a = em.createQuery("SELECT a FROM Accion a WHERE a.id = :id", Accion.class)
                    .setParameter("id", id)
                    .getSingleResult();
        } catch (NoResultException e) {
            return false;
        }
            
        accionFacade.remove(a);
        return true;
    }

    @Override
    public List<String> getEmpresas() {
        return em.createQuery("SELECT DISTINCT a.name FROM Accion a", String.class)
                .getResultList();
    }

    @Override
    public Object[] consultaVentasEmp(String empresa) {
        return (Object[]) em.createQuery("SELECT SUM(a.num), MIN(a.monto), MAX(a.monto) FROM Accion a WHERE a.name = :empresa AND a.tipo = TRUE")
                .setParameter("empresa", empresa)
                .getSingleResult();
    }

    @Override
    public Object[] consultaComprasEmp(String empresa) {
        return (Object[]) em.createQuery("SELECT SUM(a.num), MIN(a.monto), MAX(a.monto) FROM Accion a WHERE a.name = :empresa AND a.tipo = FALSE")
                .setParameter("empresa", empresa)
                .getSingleResult();
    }
    
}
